import json
from datetime import datetime
from collections import defaultdict
import itertools
from typing import List
import time
import json
import sys
import os
import shutil
import logging
from logging.handlers import TimedRotatingFileHandler
def setup_logging(
        name: str = "app",
        log_dir: str = "logs",
        level: str = "INFO",
        when: str = "D",
        backup_count: int = 7,
        fmt: str = "%(asctime)s - %(levelname)s - %(module)s:%(lineno)d - %(message)s"
) -> logging.Logger:
    """
    初始化日志配置

    参数：
        name (str): 日志名称/应用名称，默认 'app'
        log_dir (str): 日志存储目录，默认 'logs'
        level (str): 日志级别（DEBUG/INFO/WARNING/ERROR/CRITICAL），默认 'INFO'
        when (str): 日志轮换间隔单位，默认 'D'（天），可选值：
                    'S' 秒, 'M' 分, 'H' 小时, 'D' 天, 'W0'-'W6' 周
        backup_count (int): 保留的旧日志文件数量，默认7
        fmt (str): 日志格式，默认包含时间、级别、模块、行号和消息

    返回：
        logging.Logger: 配置好的Logger对象

    示例：
        >>> logger = setup_logging()
        >>> logger.info("系统启动")
    """
    try:
        # 创建日志目录
        os.makedirs(log_dir, exist_ok=True)

        # 初始化日志对象
        logger = logging.getLogger(name)
        logger.setLevel(level)

        # 清除已有处理器避免重复
        if logger.handlers:
            for handler in logger.handlers[:]:
                logger.removeHandler(handler)

        # 设置日志格式
        formatter = logging.Formatter(fmt=fmt, datefmt="%Y-%m-%d %H:%M:%S")

        # 文件处理器（按时间轮换）
        file_handler = TimedRotatingFileHandler(
            filename=os.path.join(log_dir, f"{name}.log"),
            when=when,
            backupCount=backup_count,
            encoding="utf-8"
        )
        file_handler.setFormatter(formatter)
        logger.addHandler(file_handler)

        # 控制台处理器
        console_handler = logging.StreamHandler(sys.stdout)
        console_handler.setFormatter(formatter)
        logger.addHandler(console_handler)

        return logger

    except PermissionError as e:
        sys.stderr.write(f"日志文件写入权限不足: {str(e)}\n")
        raise
    except Exception as e:
        sys.stderr.write(f"日志初始化失败: {str(e)}\n")
        raise

def generate_number_combinations(numbers: List[str] = None, output_file: str = "number_combinations.txt") -> List[str]:
    """
    生成所有可能的数字组合（允许重复）并保存到文件
    
    Args:
        numbers: 数字列表，默认为01-10
        output_file: 输出文件名
        
    Returns:
        包含所有组合的字符串列表
    """
    # 设置默认数字列表
    if numbers is None:
        numbers = [f"{i:02d}" for i in range(1, 11)]
    
    # 使用itertools.product生成所有组合（最优方法）
    combinations = list(itertools.product(numbers, repeat=2))
    
    # 格式化为字符串
    formatted_combinations = [f"{a},{b}" for a, b in combinations]
    
    
    return combinations
def analyze_number_pairs_with_threshold(save_dir,file_path, target_pairs, threshold=40):
    """
    分析指定数字对在连续期中的不中次数，只将连续不中达到阈值的结果写入JSON
    
    Args:
        file_path: JSON文件路径
        target_pairs: 要分析的数字对列表，如 [("01", "02"), ("03", "04")]
        threshold: 连续不中次数的阈值，只有达到此阈值才会写入JSON文件
    """
    
    # 读取JSON文件
    try:
        with open(file_path, 'r', encoding='utf-8') as file:
            data = json.load(file)
    except Exception as e:
        print(f"读取文件错误: {e}")
        return
    
    if 'items' not in data:
        print("错误：JSON文件中没有找到'items'字段")
        return
    
    # 按期号去重并按开奖时间排序
    items = data['items']
    unique_items = {}
    for item in items:
        unique_items[item['issue_no']] = item
    
    sorted_items = sorted(unique_items.values(), 
                         key=lambda x: datetime.strptime(x['open_time'], '%Y-%m-%d %H:%M:%S'))
    
    print(f"总共处理了 {len(sorted_items)} 期数据")
    
    # 初始化统计结果
    results = {}
    threshold_results = {}  # 存储达到阈值的结果
    
    for pair_num, (first_num, second_num) in enumerate(target_pairs, 1):
        print(f"\n{'='*60}")
        print(f"分析数字对 {pair_num}: {first_num} → {second_num}")
        print(f"{'='*60}")
        
        miss_count = 0
        current_miss = 0
        max_miss = 0
        hit_count = 0
        total_opportunities = 0
        
        analysis_details = []
        
        for i in range(len(sorted_items) - 1):
            current_item = sorted_items[i]
            next_item = sorted_items[i + 1]
            
            current_codes = [code.strip() for code in current_item['open_code'].split(',')]
            next_codes = [code.strip() for code in next_item['open_code'].split(',')]
            
            # 检查当前期第一个数字出现在哪些位置
            first_num_positions = []
            for idx, code in enumerate(current_codes):
                if code == first_num:
                    first_num_positions.append(idx)
            
            # 如果有第一个数字，检查下一期相同位置是否是第二个数字
            hit_this_time = False
            hit_positions = []
            
            for pos in first_num_positions:
                total_opportunities += 1
                if pos < len(next_codes) and next_codes[pos] == second_num:
                    hit_this_time = True
                    hit_positions.append(pos)
                    hit_count += 1
                    # 记录中奖时的连续不中次数
                    if current_miss > max_miss:
                        max_miss = current_miss
                    current_miss = 0
                    # 只要有一个位置命中就计数，然后跳出
                    break
            
            if not hit_this_time and first_num_positions:
                current_miss += 1
                miss_count = current_miss
            
            # 记录详细信息
            if first_num_positions:
                detail = {
                    'current_issue': current_item['issue_no'],
                    'next_issue': next_item['issue_no'],
                    'first_num_positions': first_num_positions,
                    'hit_positions': hit_positions,
                    'hit': hit_this_time,
                    'current_miss': current_miss if not hit_this_time else 0
                }
                analysis_details.append(detail)
        
        # 更新最终的最大不中次数
        if current_miss > max_miss:
            max_miss = current_miss
        
        # 显示结果
        print(f"数字对 {first_num} → {second_num} 的分析结果:")
        print(f"  当前连续不中次数: {current_miss}")
        print(f"  历史最大连续不中次数: {max_miss}")
        print(f"  中奖次数: {hit_count}")
        print(f"  总机会次数: {total_opportunities}")
        if total_opportunities > 0:
            hit_rate = (hit_count / total_opportunities) * 100
            print(f"  中奖率: {hit_rate:.2f}%")
        
        # 检查是否达到阈值
        if current_miss >= threshold:
            print(f"  ⚠️  警告: 当前连续不中次数已达到 {current_miss} 次，超过阈值 {threshold}!")
            threshold_results[f"{first_num}→{second_num}"] = {
                'current_miss': current_miss,
                'max_miss': max_miss,
                'hit_count': hit_count,
                'total_opportunities': total_opportunities,
                'hit_rate': hit_rate if total_opportunities > 0 else 0,
                'threshold': threshold
            }
        
        # 显示最近10期的详细情况
        print(f"\n最近10期详细情况:")
        print("-" * 80)
        for detail in analysis_details[-10:]:
            first_positions_str = ', '.join([str(p+1) for p in detail['first_num_positions']])
            if detail['hit']:
                hit_positions_str = ', '.join([str(p+1) for p in detail['hit_positions']])
                print(f"期号 {detail['current_issue']} → {detail['next_issue']}: "
                      f"位置[{first_positions_str}] 出现 {first_num} → "
                      f"下期位置[{hit_positions_str}] 出现 {second_num} ✓ 中奖!")
            else:
                print(f"期号 {detail['current_issue']} → {detail['next_issue']}: "
                      f"位置[{first_positions_str}] 出现 {first_num} → "
                      f"下期相同位置未出现 {second_num} ✗ 不中 (连续不中: {detail['current_miss']})")
        
        if current_miss == 5:
            logger.info(f"{first_num}→{second_num},开后已经连续{current_miss}没有开")
        # 保存所有结果
        results[f"{first_num}→{second_num}"] = {
            'current_miss': current_miss,
            'max_miss': max_miss,
            'hit_count': hit_count,
            'total_opportunities': total_opportunities,
            'hit_rate': hit_rate if total_opportunities > 0 else 0,
            'analysis_details': analysis_details
        }
    
    # 只有当有达到阈值的结果时，才写入JSON文件
    if threshold_results:
        filename = f"{save_dir}/high_miss_pairs_{datetime.now().strftime('%Y%m%d')}.json"
        with open(filename, 'w', encoding='utf-8') as f:
            json.dump({
                'threshold': threshold,
                'analysis_time': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
                'high_miss_pairs': threshold_results
            }, f, ensure_ascii=False, indent=2)
        print(f"\n⚠️  连续不中达到阈值 {threshold} 的数字对已保存到 {filename}")
    else:
        print(f"\n✓ 所有数字对的连续不中次数均未达到阈值 {threshold}")
    
    return {
        'target_pairs': target_pairs,
        'results': results,
        'threshold_results': threshold_results,
        'total_periods': len(sorted_items)
    }

def analyze_all_possible_pairs(file_path, threshold=40):
    """
    分析所有可能的数字对，只将连续不中达到阈值的结果写入JSON
    """
    try:
        with open(file_path, 'r', encoding='utf-8') as file:
            data = json.load(file)
    except Exception as e:
        print(f"读取文件错误: {e}")
        return
    
    items = data['items']
    unique_items = {}
    for item in items:
        unique_items[item['issue_no']] = item
    
    sorted_items = sorted(unique_items.values(), 
                         key=lambda x: datetime.strptime(x['open_time'], '%Y-%m-%d %H:%M:%S'))
    
    # 获取所有可能的数字
    all_numbers = set()
    for item in sorted_items:
        codes = [code.strip() for code in item['open_code'].split(',')]
        all_numbers.update(codes)
    
    all_numbers = sorted(list(all_numbers))
    print(f"发现 {len(all_numbers)} 个不同数字: {', '.join(all_numbers)}")
    
    # 分析所有可能的数字对
    threshold_results = {}
    
    for first_num in all_numbers:
        for second_num in all_numbers:
            if first_num == second_num:
                continue  # 跳过相同的数字对
            
            current_miss = 0
            max_miss = 0
            hit_count = 0
            total_opportunities = 0
            
            for i in range(len(sorted_items) - 1):
                current_item = sorted_items[i]
                next_item = sorted_items[i + 1]
                
                current_codes = [code.strip() for code in current_item['open_code'].split(',')]
                next_codes = [code.strip() for code in next_item['open_code'].split(',')]
                
                # 检查当前期第一个数字出现在哪些位置
                first_num_positions = []
                for idx, code in enumerate(current_codes):
                    if code == first_num:
                        first_num_positions.append(idx)
                
                # 检查下一期相同位置是否是第二个数字
                hit = False
                for pos in first_num_positions:
                    total_opportunities += 1
                    if pos < len(next_codes) and next_codes[pos] == second_num:
                        hit = True
                        hit_count += 1
                        if current_miss > max_miss:
                            max_miss = current_miss
                        current_miss = 0
                        break
                
                if not hit and first_num_positions:
                    current_miss += 1
            
            if current_miss > max_miss:
                max_miss = current_miss
            
            # 只记录达到阈值的数字对
            if current_miss >= threshold:
                pair_key = f"{first_num}→{second_num}"
                threshold_results[pair_key] = {
                    'current_miss': current_miss,
                    'max_miss': max_miss,
                    'hit_count': hit_count,
                    'total_opportunities': total_opportunities,
                    'hit_rate': (hit_count / total_opportunities * 100) if total_opportunities > 0 else 0
                }
                print(f"⚠️  {pair_key}: 当前连续不中 {current_miss} 次")
    
    # 将结果写入JSON文件
    if threshold_results:
        filename = f"all_high_miss_pairs_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json"
        with open(filename, 'w', encoding='utf-8') as f:
            json.dump({
                'threshold': threshold,
                'analysis_time': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
                'high_miss_pairs': threshold_results
            }, f, ensure_ascii=False, indent=2)
        print(f"\n⚠️  连续不中达到阈值 {threshold} 的数字对已保存到 {filename}")
        print(f"总共发现 {len(threshold_results)} 个数字对达到阈值")
    else:
        print(f"\n✓ 所有数字对的连续不中次数均未达到阈值 {threshold}")
    
    return threshold_results

def  analysic(save_dir,output_filename,threshold):
    global  logger

    logger = setup_logging(
        name="analysic_result",
        log_dir="./runtime/logs",
        level="DEBUG")
    
    file_path = os.path.join(save_dir, output_filename)
    # 要分析的数字对列表
    target_pairs = generate_number_combinations()
    
    print("开始分析彩票数字对数据...")
    
    # 分析指定数字对的不中次数
    analyze_number_pairs_with_threshold(save_dir,file_path, target_pairs, threshold)